home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / lang / mc302 / microcad / mcdraw.c < prev    next >
C/C++ Source or Header  |  1994-03-18  |  8KB  |  363 lines

  1. /*
  2.  * MICROCAD Drawing utility
  3.  *
  4.  * This is a "boiled down" set of routines to draw a MICROCAD drawing file.
  5.  * The main purpose of this program is to provide a starting point, should
  6.  * you wish to incorporate code to display a MICROCAD drawing file in one
  7.  * of your own programs. Most of this file should be useable without much
  8.  * modification.
  9.  *
  10.  * Copyright 1992-1994 Dave Dunfield
  11.  * All rights reserved.
  12.  *
  13.  * Permission granted for personal (non-commercial) use only.
  14.  *
  15.  * Compile with: cc mcdraw -fop
  16.  */
  17. #include <stdio.h>
  18.  
  19. /* Misc constants */
  20. #define    VERTICAL        480        /* Screen height */
  21. #define    HORIZONTAL        640        /* Screen width */
  22. #define    ARC_RES            64        /* Resolution of each ARC quadrant */
  23. #define    PBYTES            11        /* # of prefix bytes */
  24.  
  25. /* Drawing buffer codes */
  26. #define    LINE            0x01    /* Object is a LINE */
  27. #define    BOX                0x02    /* Object is a BOX */
  28. #define    CIRCLE            0x03    /* Object is a CIRCLE */
  29. #define    TEXT            0x04    /* Object is a TEXT string */
  30. #define    ARC                0x05    /* Object is an ARC */
  31. #define    GROUP            0x06    /* Object is a GROUP of objects */
  32. #define    ACOPY            0x07    /* Copy an object (absolute) */
  33. #define    RCOPY            0x08    /* Copy an object (relative) */
  34.  
  35. /* Global storage */
  36. char drawing[32000], font[4608], vmode;
  37. unsigned dpos;
  38.  
  39. /* 
  40.  * Sine table for drawing ARC's
  41.  */
  42. unsigned sine[] = {
  43.         0,  1608,  3216,  4821,  6424,  8022,  9616, 11204,
  44.     12785, 14359, 15924, 17479, 19024, 20557, 22078, 23586,
  45.     25079, 26557, 28020, 29465, 30893, 32302, 33692, 35062,
  46.     36410, 37736, 39040, 40320, 41575, 42806, 44011, 45190,
  47.     46341, 47464, 48559, 49624, 50660, 51665, 52639, 53581,
  48.     54491, 55368, 56212, 57022, 57797, 58538, 59243, 59913,
  49.     60547, 61144, 61705, 62228, 62714, 63162, 63571, 63943,
  50.     64276, 64571, 64826, 65043, 65220, 65358, 65457, 65516 };
  51.  
  52. /*
  53.  * Main program - read files and draw image
  54.  */
  55. main(argc, argv)
  56.     int argc;
  57.     char *argv[];
  58. {
  59.     unsigned i;
  60.     FILE *fp;
  61.  
  62.     if(argc < 2)
  63.         abort("\nUse: MCDRAW <drawing file> [font file]\n\nCopyright 1992-1994 Dave Dunfield\nAll rights reserved.\n");
  64.  
  65.     /* Read in the font file */
  66.     concat(drawing, (argc > 2) ? argv[2] : "MICROCAD", ".FNT");
  67.     fp = fopen(drawing, "rbvq");
  68.     fread(font, sizeof(font), fp);
  69.     fclose(fp);
  70.  
  71.     /* Read in drawing file */
  72.     concat(drawing, argv[1], ".DWG");
  73.     fp = fopen(drawing, "rbvq");
  74.     fread(drawing, PBYTES, fp);
  75.     i = fread(drawing, sizeof(drawing), fp);
  76.     fclose(fp);
  77.  
  78.     /* Zero unused portion of drawing file */
  79.     while(i < sizeof(drawing))
  80.         drawing[i++] = 0;
  81.  
  82.     /* Setup PC video screen */
  83.     if(!init_video())
  84.         abort("VGA required!");
  85.     video_mode(0x11);
  86.  
  87.     /* Draw all the objects */
  88.     dpos = 0;
  89.     while(!draw_object(0, 0));
  90.  
  91.     /* Wait for carriage-return and exit */
  92.     fgets(drawing, 100, stdin);
  93.     video_mode(vmode);
  94. }
  95.  
  96. /*
  97.  * Draws an object from the drawing file
  98.  */
  99. draw_object(xoffset, yoffset)
  100.     int xoffset, yoffset;
  101. {
  102.     int x, y, i, j, k, l;
  103.     char buffer[80], *ptr;
  104.  
  105.     i = drawing[dpos++];
  106.     x = dvalue() + xoffset;
  107.     y = dvalue() + yoffset;
  108.  
  109.     switch(i) {
  110.         case LINE :
  111.             line(x, y, x+dvalue(), y+dvalue());
  112.             break;
  113.         case BOX :
  114.             box(x, y, x+dvalue(), y+dvalue());
  115.             break;
  116.         case CIRCLE :
  117.             circle(x, y, dvalue());
  118.             break;
  119.         case TEXT :
  120.             i = dvalue();
  121.             ptr = buffer;
  122.             do
  123.                 *ptr++ = j = drawing[dpos++];
  124.             while(j);
  125.             text(buffer, x, y, i);
  126.             break;
  127.         case ARC:
  128.             arc(x, y, dvalue(), dvalue(), dvalue());
  129.             break;
  130.         case GROUP :
  131.             i = dvalue();
  132.             j = dpos;
  133.             while((dpos - j) < i)
  134.                 draw_object(x, y);
  135.             break;
  136.         case RCOPY :
  137.             i = dpos - 5;
  138.             i += dvalue();
  139.             goto gocopy;
  140.         case ACOPY :
  141.             i = dvalue();
  142.         gocopy:
  143.             j = dpos;
  144.             dpos = i+1;
  145.             k = dvalue();
  146.             l = dvalue();
  147.             dpos = i;
  148.             draw_object(x - k, y - l);
  149.             dpos = j;
  150.             break;
  151.         default:
  152.             abort("Corrupt drawing file!");
  153.         case 0 :
  154.             return -1; }
  155.     return 0;
  156. }
  157.  
  158. /*
  159.  * Draw a line from point (x1, y1) to (x2, y2)
  160.  */
  161. line(x1, y1, x2, y2)
  162.     int x1, y1, x2, y2;
  163. {
  164.     int i, w, h;
  165.     /* If 'X' is greater, increment through 'X' coordinate */
  166.     if((w = abs(x1 - x2)) >= (h = abs(y1 - y2))) {
  167.         if(x1 > x2) {
  168.             i = x1;
  169.             x1 = x2;
  170.             x2 = i;
  171.             i = y1;
  172.             y1 = y2;
  173.             y2 = i; }
  174.         if(y1 < y2) {
  175.             for(i=0; i < w; ++i)
  176.                 set_pixel(x1+i, y1+scale(i, h, w)); }
  177.         else {
  178.             for(i=0; i < w; ++i)
  179.                 set_pixel(x1+i, y1-scale(i, h, w)); } }
  180.     /* If 'Y' is greater, increment through 'Y' coordinate */
  181.     else {
  182.         if(y1 > y2) {
  183.             i = x1;
  184.             x1 = x2;
  185.             x2 = i;
  186.             i = y1;
  187.             y1 = y2;
  188.             y2 = i; }
  189.         if(x1 < x2) {
  190.             for(i=0; i < h; ++i)
  191.                 set_pixel(x1+scale(i, w, h), y1+i); }
  192.         else {
  193.             for(i=0; i < h; ++i)
  194.                 set_pixel(x1-scale(i, w, h), y1+i); } }
  195.  
  196.     set_pixel(x2, y2);
  197. }
  198.  
  199. /*
  200.  * Draw a box with opposite corners (x1, y1) to (x2, y2)
  201.  */
  202. box(x1, y1, x2, y2)
  203.     int x1, y1, x2, y2;
  204. {
  205.     line(x1, y1, x2, y1);        /* Top */
  206.     line(x1, y1, x1, y2);        /* Left side */
  207.     line(x2, y1, x2, y2);        /* Right side */
  208.     line(x1, y2, x2, y2);        /* Bottom */
  209. }
  210.  
  211. /*
  212.  * Draw a circle about point (x, y) of radius (r)
  213.  */
  214. circle(x, y, r)
  215.     int x, y, r;
  216. {
  217.     int i, j, k, rs, lj;
  218.  
  219.     rs = (lj = r)*r;
  220.     for(i=0; i <= r; ++i) {
  221.         j = k = sqrt(rs - (i*i));
  222.         do {
  223.             set_pixel(x+i, y+j);
  224.             set_pixel(x+i, y-j);
  225.             set_pixel(x-i, y+j);
  226.             set_pixel(x-i, y-j); }
  227.         while(++j < lj);
  228.         lj = k; }
  229. }
  230.  
  231. /*
  232.  * Draw an arc centered at (x, y), radius r at vectors v1, v2
  233.  */
  234. arc(x, y, r, v1, v2)
  235.     int x, y, r;
  236.     unsigned char v1, v2;
  237. {
  238.     int rs, i, j, ax, x1, y1, x2, y2;
  239.  
  240.     x2 = -1;
  241.     rs = r*r;
  242.  
  243.     do {
  244.         j = (ARC_RES-1) - (i = v1 & (ARC_RES-1));
  245.         switch(v1 & (ARC_RES*3)) {
  246.             case ARC_RES*0 :    /* Quadrant one */
  247.                 x1 = x + (ax = scale(r, sine[i], -1));
  248.                 y1 = y - sqrt(rs - (ax*ax));
  249.                 break;
  250.             case ARC_RES*1 :    /* Quadrant two */
  251.                 x1 = x + (ax = scale(r, sine[j], -1));
  252.                 y1 = y + sqrt(rs - (ax*ax));
  253.                 break;
  254.             case ARC_RES*2 :    /* Quadrant three */
  255.                 x1 = x - (ax = scale(r, sine[i], -1));
  256.                 y1 = y + sqrt(rs - (ax*ax));
  257.                 break;
  258.             case ARC_RES*3 :    /* Quadrant four */
  259.                 x1 = x - (ax = scale(r, sine[j], -1));
  260.                 y1 = y - sqrt(rs - (ax*ax)); }
  261.         if(x2 != -1)
  262.             line(x2, y2, x1, y1);
  263.         x2 = x1;
  264.         y2 = y1; }
  265.     while(v1++ != v2);
  266. }
  267.  
  268. /*
  269.  * Draw a text string on the screen at specified scale
  270.  */
  271. text(string, x, y, s)
  272.     char *string;
  273.     int x, y, s;
  274. {
  275.     unsigned i, j, b;
  276.     unsigned char *ptr;
  277.  
  278.     y -= scale(24, s, 100);
  279.     while(*string) {
  280.         ptr = &font[(*string++ - ' ') * 48];
  281.  
  282.         for(i=0; i < 24; ++i) {
  283.             b = (*ptr++ << 8) | *ptr++;
  284.             for(j=0; j < 16; ++j) {
  285.                 if(b & 0x8000)
  286.                     set_pixel(x+scale(j,s,100), y+scale(i,s,100));
  287.                 b <<= 1; } }
  288.         x += scale(18, s, 100); }
  289. }
  290.  
  291. /*
  292.  * Retrieve a 16 bit value from the drawing list
  293.  */
  294. dvalue()
  295. {
  296.     return (drawing[dpos++] << 8) | drawing[dpos++];
  297. }
  298.  
  299. /*
  300.  * Scale a value by a fraction, using a 32 bit intermediate result,
  301.  * and round up/down to nearest integer ressult.
  302.  */
  303. scale(value, mul, div) asm
  304. {
  305.         MOV        AX,8[BP]        ; Get value
  306.         MUL        WORD PTR 6[BP]    ; Multiply to 32 bit product
  307.         MOV        BX,4[BP]        ; Get divisor
  308.         DIV        BX                ; Divide back to 16 bit result
  309.         SHR        BX,1            ; /2 for test
  310.         JZ        scale1            ; Special case (/1)
  311.         INC        DX                ; .5 rounds up
  312.         SUB        BX,DX            ; Set 'C' if remainder > half
  313.         ADC        AX,0            ; Increment result to scale
  314. scale1:
  315. }
  316.  
  317. /*
  318.  * Initialize the video display
  319.  */
  320. init_video() asm
  321. {
  322. ; First, determine current mode for later
  323.         MOV        AH,0Fh            ; Get video mode
  324.         INT        10h                ; Call BIOS
  325.         MOV        DGRP:_vmode,AL    ; Save video mode
  326. ; Check for VGA present
  327.         MOV        AX,1A00h        ; Get display code
  328.         INT        10h                ; Call BIOS
  329.         CMP        AL,1Ah            ; VGA supported?
  330.         MOV        AL,-1            ; Assume yes
  331.         JZ        initv1            ; It does exist
  332.         XOR        AX,AX            ; Report failure
  333. initv1:
  334. }
  335.  
  336. /*
  337.  * Set active video mode & clear screen
  338.  */
  339. video_mode(mode) asm
  340. {
  341.         MOV        AL,4[BP]        ; Get mode
  342.         XOR        AH,AH            ; Func 0 - set mode
  343.         INT        10h                ; Issue mode
  344. }
  345.  
  346. /*
  347.  * Set a graphic pixel.
  348.  */
  349. set_pixel(x, y) asm
  350. {
  351.         MOV        DX,4[BP]        ; Get Y coordinate
  352.         CMP        DX,VERTICAL        ; In range?
  353.         JAE        noset            ; No, skip it
  354.         MOV        CX,6[BP]        ; Get X coordinate
  355.         CMP        CX,HORIZONTAL    ; In range?
  356.         JAE        noset            ; No, skip it
  357.         MOV        AH,0Ch            ; Write pixel function
  358.         MOV        AL,0fh            ; Pixel SET attribute
  359.         XOR        BH,BH            ; Zero page
  360.         INT        10h                ; Call int 16
  361. noset:
  362. }
  363.